package cn.agiledata.bank.transaction.action;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import cn.agiledata.bank.account.service.AccountSummary;
import cn.agiledata.bank.common.dao.AccountTemplateInter;
import cn.agiledata.bank.common.dao.BankTemplate;
import cn.agiledata.bank.common.dao.TransactionTemplate;
import cn.agiledata.bank.common.service.email.FillMoneyDown;
import cn.agiledata.bank.common.servlet.InitForString;
import cn.agiledata.bank.common.util.Constant;
import cn.agiledata.bank.common.util.DateUtil;
import cn.agiledata.bank.common.util.ForeDict;
import cn.agiledata.bank.common.util.StringUtil;
import cn.agiledata.bank.common.util.UniqueIdentityUtil;
import cn.agiledata.bank.common.util.WeatherUtil;
import cn.agiledata.bank.hibernateBean.CityInfo;
import cn.agiledata.bank.hibernateBean.SubAccount;
import cn.agiledata.bank.hibernateBean.Transaction;
import cn.agiledata.bank.transaction.exception.TransactionException;
import cn.agiledata.bank.transaction.form.MultiStepForm;
import cn.agiledata.bank.transaction.form.OfflineInpourForm;
import cn.agiledata.bank.transaction.service.GetTransaction;
import cn.agiledata.bank.transaction.service.GetTransactionImpl;
import cn.agiledata.bank.transaction.service.TransactionFactory;
import com.vnv.infrastructure.logic.IPBAppFactory;

/**
 * 线下充值
 * 
 * @author maxianbo
 * 
 */
public abstract class OfflineInpourAction extends InpourAction {

    private BankTemplate getBankTemplate() {
        return (BankTemplate) IPBAppFactory.getObj(ForeDict.BANK_TEMPLATE);
    }

    protected String getActionTypeCode(HttpServletRequest request) {
        return Constant.ACTION_TYPE_OFFLINE_INPOUR; // 交易类型：线下充值
    }

    public ActionForward assign(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        MultiStepForm form = (MultiStepForm) actionForm;
        int step = form.getStep();
        ActionForward forward;
        switch (step) {
        case 0: // 第0步进入充值流程
            forward = prepare(mapping, actionForm, request, response);
            break;
        case 1: // 第1步填写充值金额，准备汇款信息
            forward = fill(mapping, actionForm, request, response);
            break;
        case 2: // 第2步进行充值操作，显示充值结果
            forward = inpour(mapping, actionForm, request, response);
            break;
        default: // 其它步骤序数跳转到第0步，进入新的充值流程，防止错误的步骤序数被提交
            form.setStep(0);
            forward = prepare(mapping, actionForm, request, response);
        }
        // 设置新的步骤序数，最大步骤序数为2
        form.setNextStep(2);
        return forward;
    }

    public ActionForward prepare(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        ActionForward forward = super.prepare(mapping, actionForm, request,
                response);
        // 加载省份列表
        request.setAttribute("provinceList", InitForString.dataDictMap
                .get("PROVINCE_INFO"));
        return forward;
    }

    public ActionForward fill(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        ActionForward forward = super.fill(mapping, actionForm, request,
                response);
        if (hasAppExceptionMessage(request)) {
            // 加载省份列表
            request.setAttribute("provinceList", InitForString.dataDictMap
                    .get("PROVINCE_INFO"));
        }
        OfflineInpourForm form = (OfflineInpourForm) actionForm;
        BankTemplate bankTemplate = getBankTemplate();
        // 开户行省份
        String remitProvinceId = form.getRemitProvinceId();
        CityInfo remitProvince = bankTemplate.getCityInfo(remitProvinceId);
        request.setAttribute("remitProvince", remitProvince);
        // 开户行城市
        String remitCityId = form.getRemitCityId();
        CityInfo remitCity = bankTemplate.getCityInfo(remitCityId);
        request.setAttribute("remitCity", remitCity);
        return forward;
    }

    /**
     * 保存交易
     */
    private void saveTransaction(Transaction trans) {
        GetTransaction getTran = new GetTransactionImpl();
        String actionType = trans.getActionType().getId().toString();
        TransactionFactory tf = getTran.getTransaction(actionType);
        tf.saveTransaction(trans);
    }

    /**
     * 根据线下充值数据创建交易对象
     */
    protected Transaction createTransaction(OfflineInpourForm form) {
        String transId = form.getTransId();
        Transaction trans = null;
        if (!StringUtil.isStrEmpty(transId)) {
            trans = getTransactionTemplate().getTransactionByTranId(transId);
        }
        if (trans == null) {
            // 新建交易
            trans = new Transaction();
        }
        AccountTemplateInter at = getAccountTemplate();
        // 付款方：内部线下充值账户
        trans.setDebit(at.getDownSiteSubAccount());
        // 收款方：充值子账户
        SubAccount creditSubAccount = at.getSubAccountBySubAccountId(form
                .getSubAccountId());
        trans.setCredit(creditSubAccount);
        // 交易状态：待确认
        trans.setTransStatus(Constant.TRANS_STATUS_INIT);
        // 生成交易编号
        if (StringUtil.isStrEmpty(trans.getTransId()))
            trans.setTransId(UniqueIdentityUtil.getTransactionSequence());

        // 生成充值码
        if (StringUtil.isStrEmpty(trans.getVerifyCode()))
            trans.setVerifyCode(UniqueIdentityUtil.getRemitVerifyCode());
        // 交易类型
        trans.setActionType(getActionType(form.getActionType()));
        // 非担保交易
        trans.setTradeType(Constant.TRADE_TYPE_NOASSURE);
        // 充值金额
        trans.setAmount(new Double(form.getAmount()));
        // 设置记账模型
        trans.setOperate(Constant.MODEL_TYPE_REMIT);

        // 封装插入日期和修改日期
        WeatherUtil.fillCreateAndUpdateInfo(trans, creditSubAccount
                .getAccount().getId().toString());
        // 交易开始时间
        trans.setBeginDate(new Date());
        // 备注
        trans.setRemark(form.getRemark());
        // 内部状态：不做实际转账操作
        trans.setInsideStatus(Constant.INSIDE_STATUS_NO);
        // 汇款人省份
        trans.setBankProvSeq(new Long(form.getRemitProvinceId()));
        // 汇款人城市
        trans.setBankCitySeq(new Long(form.getRemitCityId()));

        // 费率
        double creditFee = getFeeRatioService().getCreditFee(trans);
        trans.setCreditFee(new Double(creditFee));
        trans.setCreditfeeRatio(getFeeRatioService().getCreditRatioHis(trans));
        if (trans.getCreditfeeRatio() != null
                && trans.getCreditfeeRatio().longValue() == 0) {
            trans.setCreditfeeRatio(null);
        }
        trans.setDebitfeeRatio(null);

        return trans;
    }

    public ActionForward inpour(ActionMapping mapping, ActionForm actionForm,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        if (!isTokenValid(request)) {
            throw TransactionException.REPEATEDLY_SUBMIT;
        }
        OfflineInpourForm form = (OfflineInpourForm) actionForm;
        Transaction trans = createTransaction(form);
        // 如果是企业用户记录其操作员
        if (isCorpAccount(request)) {
            AccountSummary accountsummary = WeatherUtil
                    .getLoingInfoFromSession(request);
            trans.setOperatorSeq(accountsummary.getOperatorCode().toString());
        }
        try {
            saveTransaction(trans);
        } catch (RuntimeException e) {
            throw TransactionException.TRANSACTION_FAILED;
        }
        request.setAttribute("transaction", trans);
        request.setAttribute("actualAmount", getActualInpourAmount(trans));

        TransactionTemplate tt = getTransactionTemplate();
        NumberFormat nf = new DecimalFormat("#0.00#");
        FillMoneyDown fmd = (FillMoneyDown) IPBAppFactory
                .getObj("fillMoneyDown");
        String now = DateUtil.date2String(new Date());
        String url = WeatherUtil.getRootFromSession(request);
        String strSmsVm = "";
        if (trans.getBankName() == null) {

            url = url + "/images/postRemitExample.gif";
            strSmsVm = "sms-postRemitInpour.vm";
            fmd.setWarn("邮局");
/*            fmd.setWarn("  您通过邮局汇款充值￥"
                    + nf.format(trans.getAmount().doubleValue())
                    + "元的要求正在处理中，请等待确认。<br/>"
                    + " 您可以按下图表单格式及内容，前往邮局填写表单即可完成充值。<br/>"
                    + "请务必于表单附言处准确填写您的8位充值号码：" + trans.getVerifyCode()
                    + "，本号<br/>" + "码是系统为本次充值操作自动生成，将作为为您有效充值的凭证。<br/>");*/
        } else {

            url = url + "/images/bankRemitExample.gif";
            fmd.setWarn("银行");
/*            fmd.setWarn("  您通过银行汇款充值￥"
                    + nf.format(trans.getAmount().doubleValue())
                    + "元的要求正在处理中，请等待确认。<br/>"
                    + " 您可以按下图表单格式及内容，前往银行填写表单即可完成充值。<br/>"
                    + "请务必于表单用途处准确填写您的8位充值号码：" + trans.getVerifyCode()
                    + "，本号<br/>" + "码是系统为本次充值操作自动生成，将作为为您有效充值的凭证。<br/>");*/
            
            strSmsVm = "sms-bankRemitInpour.vm";	// 银行汇款充值
        }
        if (tt.ifSendMail(trans.getCredit().getAccount(),
                Constant.FILLMONEYDOWN)) {

            fmd.setUrl(url);
            fmd.sendMail(trans, null);
        }
        if (tt.ifSendMobile(trans.getCredit().getAccount(),
                Constant.FILLMONEYDOWN)) {
        	Map mapParam = new HashMap();
        	mapParam.put("time", now);
        	mapParam.put("amount", nf.format(trans.getAmount().doubleValue()));
        	mapParam.put("verifyCode", trans.getVerifyCode());
            fmd.sendSms(trans, null,strSmsVm,mapParam);
        }

        resetToken(request);
        return mapping.findForward(ForeDict.FORWARD_STEP_3);
    }
}
